import sqlite3, json
from .node import Node, Input, Output, Link

conn = sqlite3.connect("file.db", check_same_thread=False)


def get_node(id: int) -> Node:
    # 查询
    cur = conn.cursor()
    cur.execute(
        "select id, name, node_id, type, inputs, outputs, widgets_values, properties from node where id = ?",
        (id,),
    )
    row = cur.fetchone()
    return Node(
        int(row[0]),
        int(row[2]),
        row[3],
        [Input.from_dict(d) for d in json.loads(row[4])],
        [Output.from_dict(d) for d in json.loads(row[5])],
        json.loads(row[6]),
        row[7],
    )


def get_node_by_name_and_id(name: str, id: int) -> Node:
    # 查询
    cur = conn.cursor()
    cur.execute(
        "select id, name, node_id, type, inputs, outputs, widgets_values, properties from node where name = ? and node_id = ?",
        (name, id),
    )
    row = cur.fetchone()
    return Node(
        int(row[0]),
        int(row[2]),
        row[3],
        [Input.from_dict(d) for d in json.loads(row[4])],
        [Output.from_dict(d) for d in json.loads(row[5])],
        json.loads(row[6]),
        row[7],
    )


def save_link(name: str, link: Link):
    # 保存
    cur = conn.cursor()
    cur.execute(
        "insert into link (name, origin_node_id, origin_slot, target_node_id, target_slot, type) values (?,?,?,?,?,?)",
        (
            name,
            link.origin_node_id,
            link.origin_slot,
            link.target_node_id,
            link.target_slot,
            link.type,
        ),
    )
    conn.commit()


def save_node(node: Node, blueprint: str):
    # 保存
    cur = conn.cursor()
    cur.execute(
        "insert into node (name, node_id, type, inputs, outputs, widgets_values, properties) values (?,?,?,?,?,?,?)",
        (
            blueprint,
            node.node_id,
            node.type,
            json.dumps([input.to_dict() for input in node.inputs]),
            json.dumps([output.to_dict() for output in node.outputs]),
            json.dumps(node.widgetValues),
            json.dumps(node.properties),
        ),
    )
    conn.commit()


def update_node(node: Node):
    # 保存
    cur = conn.cursor()
    cur.execute(
        "update node set inputs = ?, outputs = ?, widgets_values = ? where id = ?",
        (
            json.dumps([input.to_dict() for input in node.inputs]),
            json.dumps([output.to_dict() for output in node.outputs]),
            json.dumps(node.widgetValues),
            node.id,
        ),
    )
    conn.commit()


def get_link(id) -> list[Link]:
    # 查询
    cur = conn.cursor()
    cur.execute(
        "select origin_node_id, origin_slot, target_node_id, target_slot, type from link where origin_node_id = ?",
        (id,),
    )
    rows = cur.fetchall()
    return [
        Link(int(row[0]), int(row[1]), int(row[2]), int(row[3]), row[4]) for row in rows
    ]


def trigger(id: int):
    # 查找node信息
    node: Node = get_node(id)
    links: list[Link] = get_link(id)

    # 实例化模块
    from .util import by_path

    cls: type = by_path(node.type)
    used_links: list[Link] = cls().process(node, links)

    # 保存参数
    update_node(node)

    # 保存参数
    for link in used_links:
        # 获取输入值
        origin_slot = link.origin_slot
        input_value = node.outputs[origin_slot].value

        # 保存输入值
        target_id = link.target_node_id
        target_slot = link.target_slot
        t_node = get_node(target_id)
        t_node.inputs[target_slot].value = input_value

        # 保存node
        update_node(t_node)

    # 触发下一个
    for link in used_links:
        trigger(link.target_node_id)
